﻿using Microsoft.AspNetCore.Authorization;
using Newtonsoft.Json;

namespace Admin.NET.Application.Service.EG_WMS_Inventory;
/// <summary>
/// 库存主表接口
/// </summary>
[ApiDescriptionSettings(ApplicationConst.GroupName, Order = 100)]
public class EGInventoryService : IDynamicApiController, ITransient
{
    #region 实体引用


    private readonly SqlSugarRepository<Entity.EG_WMS_Inventory> _rep;
    private readonly SqlSugarRepository<Entity.EG_WMS_Materiel> _materiel;
    private readonly SqlSugarRepository<Entity.EG_WMS_InAndOutBound> _inandoutbound;
    private readonly SqlSugarRepository<Entity.EG_WMS_Storage> _storage;
    #endregion

    #region 关系注入

    public EGInventoryService
        (
        SqlSugarRepository<Entity.EG_WMS_Inventory> rep,
        SqlSugarRepository<Entity.EG_WMS_Materiel> materiel,
        SqlSugarRepository<Entity.EG_WMS_InAndOutBound> inandoutbound,
        SqlSugarRepository<Entity.EG_WMS_Storage> storage

        )
    {
        _rep = rep;
        _materiel = materiel;
        _inandoutbound = inandoutbound;
        _storage = storage;
    }
    #endregion

    #region 当日的入库数量

    /// <summary>
    /// 当日的入库数量
    /// </summary>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "DailyInBoundQuantity")]
    public async Task<List<DailyInOutBoundQuantityDto>> DailyInBoundQuantity()
    {

        //string sql = "SELECT DATE_FORMAT(InAndOutBoundTime, '%Y-%m-%d %H') as time, SUM(InAndOutBoundCount) " +
        //     "as count FROM eg_wms_inandoutbound WHERE InAndOutBoundTime >= CURDATE() AND InAndOutBoundTime<CURDATE() +INTERVAL 1 DAY GROUP BY time  ORDER BY  time";

        DateTime todayStart = DateTime.Today;
        DateTime todayEnd = todayStart.AddDays(1);
        return await _inandoutbound.AsQueryable()
                                 .Where(x => x.InAndOutBoundStatus == 1 && x.InAndOutBoundType == 0 && x.SuccessOrNot == 0)
                                 .Where(x => x.InAndOutBoundTime >= todayStart && x.InAndOutBoundTime < todayEnd)
                                 .GroupBy(x => SqlFunc.MappingColumn(x.InAndOutBoundTime.Value.ToString(), "DATE_FORMAT(InAndOutBoundTime, '%Y-%m-%d %H')"))
                                 .Select(x => new DailyInOutBoundQuantityDto
                                 {
                                     HourTime = SqlFunc.MappingColumn(x.InAndOutBoundTime.Value.ToString(), "DATE_FORMAT(InAndOutBoundTime, '%Y-%m-%d %H')"),
                                     SumCount = (int)SqlFunc.AggregateSum(x.InAndOutBoundCount)
                                 })
                                 .ToListAsync();




    }

    #endregion

    #region 当日的出库数量

    /// <summary>
    /// 当日的出库数量
    /// </summary>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "DailyOutBoundQuantity")]
    public async Task<List<DailyInOutBoundQuantityDto>> DailyOutBoundQuantity()
    {

        DateTime todayStart = DateTime.Today;
        DateTime todayEnd = todayStart.AddDays(1);
        return await _inandoutbound.AsQueryable()
                                 .Where(x => x.InAndOutBoundStatus == 3 && x.InAndOutBoundType == 1 && x.SuccessOrNot == 0)
                                 .Where(x => x.InAndOutBoundTime >= todayStart && x.InAndOutBoundTime < todayEnd)
                                 .GroupBy(x => SqlFunc.MappingColumn(x.InAndOutBoundTime.Value.ToString(), "DATE_FORMAT(InAndOutBoundTime, '%Y-%m-%d %H')"))
                                 .Select(x => new DailyInOutBoundQuantityDto
                                 {
                                     HourTime = SqlFunc.MappingColumn(x.InAndOutBoundTime.Value.ToString(), "DATE_FORMAT(InAndOutBoundTime, '%Y-%m-%d %H')"),
                                     SumCount = (int)SqlFunc.AggregateSum(x.InAndOutBoundCount)
                                 })
                                 .ToListAsync();




    }

    #endregion

    #region 分页查询库存主表
    /// <summary>
    /// 分页查询库存主表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Page")]
    public async Task<SqlSugarPagedList<EGInventoryOutput>> Page(EGInventoryInput input)
    {
        var query = _rep.AsQueryable()
            // 库存编号
            //.WhereIF(!string.IsNullOrWhiteSpace(input.InventoryNum), u => u.InventoryNum.Contains(input.InventoryNum.Trim()))
            .WhereIF(input.ICountAll > 0, u => u.ICountAll == input.ICountAll)
            .WhereIF(input.IUsable > 0, u => u.IUsable == input.IUsable)
            .WhereIF(input.IFrostCount > 0, u => u.IFrostCount == input.IFrostCount)
            .WhereIF(input.IWaitingCount > 0, u => u.IWaitingCount == input.IWaitingCount)
            // 物料编号
            .WhereIF(!string.IsNullOrWhiteSpace(input.MaterielNum), u => u.MaterielNum == input.MaterielNum.Trim())
            // 备注
            .WhereIF(!string.IsNullOrWhiteSpace(input.InventoryRemake), u => u.InventoryRemake == input.InventoryRemake.Trim())
            // 出库状态
            .WhereIF(input.OutboundStatus > 0, u => u.OutboundStatus == input.OutboundStatus)
            // 获取创建日期
            .WhereIF(input.CreateTime > DateTime.MinValue, u => u.CreateTime >= input.CreateTime)
            // 倒序
            .OrderBy(it => it.CreateTime, OrderByType.Desc)
            .Select<EGInventoryOutput>()
;
        query = query.OrderBuilder(input);
        return await query.ToPagedListAsync(input.Page, input.PageSize);
    }
    #endregion

    #region 更新库存主表
    /// <summary>
    /// 更新库存主表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Update")]
    public async Task Update(UpdateEGInventoryInput input)
    {
        var entity = input.Adapt<Entity.EG_WMS_Inventory>();
        await _rep.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
    }
    #endregion

    #region 模糊查询符条件的数据（根据物料名称、编号、类别）
    /// <summary>
    /// 模糊查询符条件的数据（根据物料名称、编号、类别）
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Detail")]
    public async Task<List<EGInventoryAndMaterielDto>> Detail(QueryByIdEGInventoryInput input)
    {
        List<string> materielNums = new List<string>();
        List<EGInventoryAndMaterielDto> EGInventoryAndMaterielData = new List<EGInventoryAndMaterielDto>();

        try
        {
            var materielsData = _materiel.AsQueryable()
                                         .Where(u => u.MaterielName.Contains(input.MaterielName) || u.MaterielNum.Contains(input.MaterielNum) || u.MaterielType.Contains(input.MaterielType))
                                         .ToList();


            if (materielsData.Count != 0)
            {
                // 得到模糊查询里面的物料编号  
                foreach (var item in materielsData)
                {
                    materielNums.Add(item.MaterielNum);
                }

                for (int i = 0; i < materielNums.Count; i++)
                {
                    string num = materielNums[i];

                    try
                    {
                        var materieItem = await _materiel.GetFirstAsync(u => u.MaterielNum == num);
                        var inventoryItem = await _rep.GetFirstAsync(u => u.MaterielNum == num);
                        // 物料名称  
                        string materielnum = materieItem.MaterielNum;
                        // 物料名称  
                        string materiename = materieItem.MaterielName;
                        // 规格  
                        string materielspecs = materieItem.MaterielSpecs;
                        // 在库数量  
                        int? icountall = inventoryItem.ICountAll;
                        // 可用数量  
                        int? iusable = inventoryItem.IUsable;

                        EGInventoryAndMaterielDto inventory = new EGInventoryAndMaterielDto()
                        {
                            MaterielNum = materielnum,
                            MaterielName = materiename,
                            MaterielSpecs = materielspecs,
                            ICountAll = icountall,
                            IUsable = iusable,
                        };
                        EGInventoryAndMaterielData.Add(inventory);
                    }
                    catch (Exception ex)
                    {
                        throw Oops.Oh(ex.Message, ex);
                    }
                }
            }
            else
            {
                throw Oops.Oh("查询不到记录");
            }
        }
        catch (Exception ex)
        {
            throw Oops.Oh(ex.Message);
        }
        return EGInventoryAndMaterielData;
    }

    #endregion

    #region 获取库存主表列表
    /// <summary>
    /// 获取库存主表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "List")]
    public async Task<List<EGInventoryOutput>> List([FromQuery] EGInventoryInput input)
    {
        return await _rep.AsQueryable().Select<EGInventoryOutput>().ToListAsync();
    }

    #endregion

    #region 根据库位信息获取数据

    /// <summary>
    /// 根据库位信息获取数据
    /// </summary>
    /// <param name="StorageNum"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "StorageInventoryData")]
    [AllowAnonymous]
    public List<MaterielProductDto> StorageInventoryData([Required] string StorageNum)
    {
        var storagedata = _storage.GetFirst(x => x.StorageNum == StorageNum) ?? throw Oops.Oh("库位编号不存在！");
        return _rep.AsQueryable()
                   .InnerJoin<EG_WMS_InventoryDetail>((a, b) => a.InventoryNum == b.InventoryNum)
                   .Where((a, b) => a.OutboundStatus == 0 && string.IsNullOrEmpty(a.OutBoundNum))
                   .Where((a, b) => b.StorageNum == StorageNum)
                   .Select((a, b) => new MaterielProductDto
                   {
                       MaterielNum = a.MaterielNum,
                       ProductCount = (int)a.ICountAll,
                       ProductionDate = (DateTime)a.ProductionDate,
                       ProductionLot = b.ProductionLot,
                   })
                   .ToList();

    }

    #endregion

    #region 根据组号查询本组库存信息

    /// <summary>
    /// 根据组号查询本组库存信息
    /// </summary>
    /// <returns></returns>
    [ApiDescriptionSettings]
    [AllowAnonymous]
    public async Task<List<GroupInventoryStorageDto>> GroupInventoryData(QueryInventoryGroup model)
    {

        var groupstorageall = _storage.AsQueryable()
                    .WhereIF(!string.IsNullOrEmpty(model.StorageGroup), x => x.StorageGroup == model.StorageGroup)
                    .OrderBy(x => x.StorageNum, OrderByType.Asc)
                    .ToList();

        var storagenumlist = groupstorageall.Select(x => x.StorageNum).ToList();

        var invdata = _rep.AsQueryable()
                     .Includes(a => a.Inventory)
                     .Where(x => x.OutboundStatus == 0)
                     //.Where(x => storagenumlist.Contains(x.Inventory.StorageNum))
                     .ToList()
                     .Adapt<List<MaterielProductTempDto>>();

        var listdata = groupstorageall.AsQueryable().GroupJoin(invdata,
             x => x.StorageNum,
             y => y.StorageNum,
             (x, Collection) => new GroupInventoryStorageDto
             {
                 StorageNum = x.StorageNum,
                 StorageGroup = x.StorageGroup,
                 InventoryDatas = Collection.Any() ? Collection.Adapt<List<MaterielProductDto>>() : null
             })
             .ToList();

        return listdata;
        //if (!string.IsNullOrEmpty(model.StorageGroup))
        //{
        //    var storagedata = _storage.AsQueryable().Where(x => x.StorageGroup == model.StorageGroup).OrderBy(x => x.StorageNum, OrderByType.Asc).Select(x => x.StorageNum).ToList();
        //    if (storagedata.Count == 0)
        //    {
        //        throw Oops.Oh("没有查询到该组别！");
        //    }
        //    List<GroupInventoryStorageDto> groupInventorylist = new List<GroupInventoryStorageDto>();
        //    for (var i = 0; i < storagedata.Count; i++)
        //    {
        //        GroupInventoryStorageDto groupInventory = new GroupInventoryStorageDto();
        //        var invdata = _rep.AsQueryable()
        //                    .InnerJoin<EG_WMS_InventoryDetail>((a, b) => a.InventoryNum == b.InventoryNum)
        //                    .Where((a, b) => a.OutboundStatus == 0 && string.IsNullOrEmpty(a.OutBoundNum))
        //                    .Where((a, b) => b.StorageNum == storagedata[i])
        //                    .Select((a, b) => new MaterielProductDto
        //                    {
        //                        MaterielNum = a.MaterielNum,
        //                        ProductCount = (int)a.ICountAll,
        //                        ProductionDate = (DateTime)a.ProductionDate,
        //                        ProductionLot = b.ProductionLot,
        //                    })
        //                    .ToList();
        //        groupInventory.StorageNum = storagedata[i];
        //        groupInventory.StorageGroup = model.StorageGroup;
        //        groupInventory.InventoryDatas = invdata;
        //        groupInventorylist.Add(groupInventory);
        //    }
        //    return groupInventorylist;
        //}
        //else
        //{
        //    查询得到所有的组别
        //   var allgroup = _storage.AsQueryable().GroupBy(x => x.StorageGroup).OrderBy(x => x.StorageNum, OrderByType.Asc).Distinct().Select(x => x.StorageGroup).ToList();
        //    List<GroupInventoryStorageDto> groupInventorylist = new List<GroupInventoryStorageDto>();
        //    for (int q = 0; q < allgroup.Count; q++)
        //    {
        //        根据组别查询每组库位
        //       var groupstorageall = _storage.AsQueryable().Where(x => x.StorageGroup == allgroup[q]).OrderBy(x => x.StorageNum, OrderByType.Asc).Select(x => x.StorageNum).ToList();
        //        for (var z = 0; z < groupstorageall.Count; z++)
        //        {
        //            GroupInventoryStorageDto groupInventory = new GroupInventoryStorageDto();
        //            var invdata = _rep.AsQueryable()
        //                        .InnerJoin<EG_WMS_InventoryDetail>((a, b) => a.InventoryNum == b.InventoryNum)
        //                        .Where((a, b) => a.OutboundStatus == 0 && string.IsNullOrEmpty(a.OutBoundNum))
        //                        .Where((a, b) => b.StorageNum == groupstorageall[z])
        //                        .Select((a, b) => new MaterielProductDto
        //                        {
        //                            MaterielNum = a.MaterielNum,
        //                            ProductCount = (int)a.ICountAll,
        //                            ProductionDate = (DateTime)a.ProductionDate,
        //                            ProductionLot = b.ProductionLot,
        //                        })
        //                        .ToList();
        //            groupInventory.StorageNum = groupstorageall[z];
        //            groupInventory.StorageGroup = allgroup[q];
        //            groupInventory.InventoryDatas = invdata;
        //            groupInventorylist.Add(groupInventory);
        //        }
        //    }
        //    return groupInventorylist;
        //else
        //{
        // 查询得到所有的组别
        //List<GroupInventoryStorageDto> groupInventorylist = new List<GroupInventoryStorageDto>();
        //根据组别查询每组库位
        //for (var z = 0; z < groupstorageall.Count; z++)
        //{

        //    GroupInventoryStorageDto groupInventory = new GroupInventoryStorageDto();
        //    var invdata = _rep.AsQueryable()
        //                .InnerJoin<EG_WMS_InventoryDetail>((a, b) => a.InventoryNum == b.InventoryNum)
        //                .Where((a, b) => a.OutboundStatus == 0 && string.IsNullOrEmpty(a.OutBoundNum))
        //                .Where((a, b) => b.StorageNum == groupstorageall[z].StorageNum)
        //                .Select((a, b) => new MaterielProductDto
        //                {
        //                    MaterielNum = a.MaterielNum,
        //                    ProductCount = (int)a.ICountAll,
        //                    ProductionDate = (DateTime)a.ProductionDate,
        //                    ProductionLot = b.ProductionLot,
        //                })
        //                .ToList();
        //    groupInventory.StorageNum = groupstorageall[z].StorageNum;
        //    groupInventory.StorageGroup = groupstorageall[z].StorageGroup;
        //    groupInventory.InventoryDatas = invdata;
        //    groupInventorylist.Add(groupInventory);
        //}
        //return groupInventorylist;
        //}
    }
    #endregion

    #region 根据条件查询库存信息

    /// <summary>
    /// 根据条件查询库存信息
    /// </summary>
    /// <param name="model">判断条件</param>
    /// <returns></returns>
    [HttpPost]
    [AllowAnonymous]
    [ApiDescriptionSettings(Name = "QueryInventoryInformationAccordingConditions")]
    public List<StorageInventoryDataDto> QueryInventoryInformationAccordingConditions(SelectInventoryConditionDto model)
    {
        if (!string.IsNullOrEmpty(model.StorageNum))
        {
            Entity.EG_WMS_Storage storagedata = _storage.GetFirst(x => x.StorageNum == model.StorageNum) ?? throw Oops.Oh("库位编号不存在！");
        }
        if (!string.IsNullOrEmpty(model.MaterielNum))
        {
            Entity.EG_WMS_Materiel materieldata = _materiel.GetFirst(x => x.MaterielNum == model.MaterielNum) ?? throw Oops.Oh("物料编号不存在！");
        }
        return _rep.AsQueryable()
             .InnerJoin<EG_WMS_InventoryDetail>((a, b) => a.InventoryNum == b.InventoryNum)
             .Where((a, b) => a.OutboundStatus == 0)
             .WhereIF(model.StorageNum != null, (a, b) => b.StorageNum == model.StorageNum)
             .WhereIF(model.MaterielNum != null, (a, b) => a.MaterielNum == model.MaterielNum)
             .WhereIF(model.ProductionLot != null, (a, b) => b.ProductionLot == model.ProductionLot)
             .WhereIF(model.ProductionDate != null, (a, b) => a.ProductionDate.Value.ToString("yyyy-MM-dd").Contains(model.ProductionDate.Value.ToString("yyyy-MM-dd")))
             .GroupBy((a, b) => b.StorageNum)
             .OrderBy((a, b) => b.StorageNum, OrderByType.Asc)
             .Select((a, b) => new StorageInventoryDataDto
             {
                 StorageNum = b.StorageNum,
                 MaterielNum = a.MaterielNum,
                 ICountAll = (int)SqlFunc.AggregateSum(a.ICountAll),
                 ProductionLot = b.ProductionLot,
                 ProductionDate = (DateTime)a.ProductionDate,
             })
             .ToList();

    }

    #endregion

    //-------------------------------------//-------------------------------------//

    #region 模糊查询（根据物料编号和物料名称和物料规格查询）
    //public async Task<List<EGInventoryAndMaterielDto>> Get([FromQuery] QueryByIdEGInventoryInput input)
    //{

    //    模糊查询（根据物料编号和物料名称和物料规格查询）
    //    List<string> materielNums = new List<string>();
    //    List<EGInventoryAndMaterielDto> EGInventoryAndMaterielData = new List<EGInventoryAndMaterielDto>();

    //    List<EGMateriel> materielsData = await _materiel.GetListAsync
    //        (
    //            u => u.MaterielNum.Contains(input.MaterielNum) ||
    //            u.MaterielName.Contains(input.MaterielName) ||
    //            u.MaterielSpecs.Contains(input.MaterielSpecs)
    //        );
    //    if (materielsData != null)
    //    {
    //        得到模糊查询里面的物料编号
    //        foreach (var item in materielsData)
    //        {
    //            materielNums.Add(item.MaterielNum);
    //        }

    //        for (int i = 0; i < materielNums.Count; i++)
    //        {
    //            string num = materielNums[i];

    //            var materieItem = await _materiel.GetFirstAsync(u => u.MaterielNum == num);
    //            var inventoryItem = await _rep.GetFirstAsync(u => u.MaterielNum == num);
    //            物料名称
    //           var materielnum = materieItem.MaterielNum;
    //            物料名称
    //           var materiename = materieItem.MaterielName;
    //            规格
    //           var materielspecs = materieItem.MaterielSpecs;
    //            在库数量
    //           var icountall = inventoryItem.ICountAll;
    //            可用数量
    //           var iusable = inventoryItem.IUsable;


    //            EGInventoryAndMaterielDto inventory = new EGInventoryAndMaterielDto()
    //            {
    //                MaterielNum = materielnum,
    //                MaterielName = materiename,
    //                MaterielSpecs = materielspecs,
    //                ICountAll = (int)icountall,
    //                IUsable = (int)iusable,

    //            };
    //            EGInventoryAndMaterielData.Add(inventory);
    //        }

    //    }
    //    return EGInventoryAndMaterielData;

    //}
    #endregion

}

public class QueryInventoryGroup
{
    public string StorageGroup { get; set; }
}